import { memo, forwardRef } from 'react'
import { useDrag, useDrop } from 'react-dnd'
import classNames from 'classnames'
import IconFont from '@/components/IconFont'
import { isUndefined } from 'loadsh'
import styles from './index.module.less'

const FieldItem = memo(
  forwardRef(({ field, accept, requestKey, findField, moveField }, ref) => {
    const { fieldClassify, fieldType } = field
    const { index: originalIndex } = findField(field.id, requestKey)
    const [_, drag] = useDrag({
      type: `sort_${fieldClassify}`,
      item: () => field,
      end: (item, monitor) => {
        const didDrop = monitor.didDrop()
        if (!didDrop) {
          const { id: droppedId } = item
          const { index: droppedIndex } = findField(droppedId, requestKey)
          moveField(item, originalIndex, droppedIndex, requestKey)
        }
      }
    })

    const [, drop] = useDrop(() => ({
      accept: accept.map((v) => `sort_${v}`),
      hover({ id: draggedId }) {
        if (draggedId !== field.id) {
          const { index: draggedIndex, field: draggedField } = findField(draggedId, requestKey)
          moveField(draggedField, draggedIndex, originalIndex, requestKey)
        }
      }
    }))

    return (
      <div
        ref={(node) => drag(drop(node))}
        className={classNames(styles['field-item'], styles[fieldClassify])}
      >
        <IconFont style={{ fontSize: '14px' }} type={`icon-${fieldType}-${fieldClassify}`} />
        <span className="ellipsis">{field.title}</span>
      </div>
    )
  })
)

const QueryItem = memo(
  ({ requestKey, requestField, value: fields = [], onChange, findField, moveField }) => {
    const { label, type, required, limit = -1 } = requestField

    const accept = isUndefined(type) ? ['dimension', 'measure'] : [type]
    const [{ canDrop }, drop] = useDrop({
      accept,
      drop: (item, monitor) => {
        const isOver = monitor.isOver()
        if (isOver) {
          onChange(item, requestKey)
        }
      },
      canDrop: () => {
        return fields.length !== limit
      },
      collect: (monitor) => ({
        canDrop: monitor.canDrop()
      })
    })

    return (
      <div className={styles['query-item']}>
        <label className={required ? styles['required'] : ''}>
          {label}
          {type ? ` / ${type === 'dimension' ? '维度' : '度量'}` : ''}
        </label>
        <div
          ref={drop}
          className={classNames(styles['field-list'], { [styles.dropable]: canDrop })}
        >
          {fields.length ? (
            <>
              {fields.map((item) => (
                <FieldItem
                  key={item.id}
                  field={item}
                  accept={accept}
                  requestKey={requestKey}
                  onChange={onChange}
                  findField={findField}
                  moveField={moveField}
                />
              ))}
            </>
          ) : (
            <div className={styles['item-placeholder']}>从左侧拖入字段</div>
          )}
        </div>
      </div>
    )
  }
)

const QueryFields = memo((props) => {
  const { requestFields, value, ...attrs } = props
  return (
    <div className={styles['query-field']}>
      <div className={styles['query-list']}>
        {Object.entries(requestFields).map(([key, item]) => (
          <QueryItem key={key} {...attrs} requestKey={key} requestField={item} value={value[key]} />
        ))}
      </div>
    </div>
  )
})

export default QueryFields
